package com.ruoyi.project.module.Job;

import com.crawler.XxlCrawler;
import com.crawler.annotation.PageFieldSelect;
import com.crawler.annotation.PageSelect;
import com.crawler.conf.XxlCrawlerConf;
import com.crawler.parser.PageParser;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.ScheduleConstants;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.project.module.item.domain.Item;
import com.ruoyi.project.module.item.service.IItemService;
import com.ruoyi.project.module.itemDetail.domain.ItemDetail;
import com.ruoyi.project.module.itemDetail.service.IItemDetailService;
import com.ruoyi.project.monitor.job.domain.Job;
import com.ruoyi.project.monitor.job.domain.JobLog;
import com.ruoyi.project.monitor.job.service.IJobLogService;
import lombok.Data;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

import static com.ruoyi.framework.aspectj.lang.constant.CategoryType.BUYER_CITY_SELECTED_DB;

//@Component("CrawlItemDetail")
public class CrawlItemDetail {

    @Autowired
    private IItemService itemService;
    @Autowired
    private IItemDetailService iItemDetailService;

    IJobLogService jobLogService = (IJobLogService) SpringUtils.getBean(IJobLogService.class);

    private boolean END_STATE = true;

    //探测 最大物品库存的实体
    @Data
    @PageSelect(cssQuery = "body")
    public static class InventoryPageVo {

        //是否有错误警告
        @PageFieldSelect(cssQuery = "div.alert", selectType = XxlCrawlerConf.SelectType.HTML)
        private String alert;

        //拉取需要的的post参数 作为拉取 添加购物车的参数
        @PageFieldSelect(cssQuery = "#addItemToCart > #hitsCfs", selectType = XxlCrawlerConf.SelectType.VAL)
        private String add_HitsCfs;

        @PageFieldSelect(cssQuery = "#addItemToCart > #hitsCfsMeta", selectType = XxlCrawlerConf.SelectType.VAL)
        private String add_HitsCfsMeta;

        @PageFieldSelect(cssQuery = "#addItemToCart > #action", selectType = XxlCrawlerConf.SelectType.VAL)
        private String add_Action;

        @PageFieldSelect(cssQuery = "#addItemToCart > #id_unit", selectType = XxlCrawlerConf.SelectType.VAL)
        private String add_Id_unit;

        @PageFieldSelect(cssQuery = "#addItemToCart > #redirect_to", selectType = XxlCrawlerConf.SelectType.VAL)
        private String add_Redirect_to;

        @PageFieldSelect(cssQuery = "#addItemToCart > #id_bundle", selectType = XxlCrawlerConf.SelectType.VAL)
        private String add_Id_bundle;

        //商品的ean信息等  列表
        @PageFieldSelect(cssQuery = "#specs-full dd", selectType = XxlCrawlerConf.SelectType.HTML)
        private List<String> specifications;

        //商品的ean信息名字等 用于找到ean是第几个
        @PageFieldSelect(cssQuery = "#specs-full dt", selectType = XxlCrawlerConf.SelectType.HTML)
        private List<String> specificationNames;


        @PageFieldSelect(cssQuery = "select.unit-quantity-input", selectType = XxlCrawlerConf.SelectType.HTML)
        private List<String> shopInventoryList;

        //第一层的商品数量
        @PageFieldSelect(cssQuery = ".unit-labels > b > span", selectType = XxlCrawlerConf.SelectType.HTML)
        private String item_Detail_Inventory;

        //第一层的商品名称
        @PageFieldSelect(cssQuery = "h1", selectType = XxlCrawlerConf.SelectType.HTML)
        private String item_Detail_Name;

        //第一层商铺名称
        @PageFieldSelect(cssQuery = "a > b", selectType = XxlCrawlerConf.SelectType.HTML)
        private String item_Detail_Store_Name;

        //第二层的商品数量
        @PageFieldSelect(cssQuery = "[name=\"amount_cart_unit\"]", selectType = XxlCrawlerConf.SelectType.VAL)
        private List<String> item_Detail_Inventory2;

        //第二层的商品名称
        @PageFieldSelect(cssQuery = "a > h6", selectType = XxlCrawlerConf.SelectType.HTML)
        private List<String> item_Detail_Name2;

        //第二层商铺名称
        @PageFieldSelect(cssQuery = "dd > small", selectType = XxlCrawlerConf.SelectType.HTML)
        private List<String> item_Detail_Store_Name2;

        //第二层的十以下的物品标志
        @PageFieldSelect(cssQuery = "b.txtcolor-alert", selectType = XxlCrawlerConf.SelectType.HTML)
        private List<String> txt_Alert;

        //第二层的商品链接
        @PageFieldSelect(cssQuery = ".small-10 > a", selectType = XxlCrawlerConf.SelectType.ATTR, selectVal = "href")
        private List<String> item_Detail_Href2;

        //拉取最大库存需要的参数
        @PageFieldSelect(cssQuery = ".unit-quantity-form > #hitsCfs", selectType = XxlCrawlerConf.SelectType.VAL)
        private List<String> hitsCfsList;

        @PageFieldSelect(cssQuery = ".unit-quantity-form > #hitsCfsMeta", selectType = XxlCrawlerConf.SelectType.VAL)
        private List<String> hitsCfsMetaList;

        @PageFieldSelect(cssQuery = "[name=\"id_unit\"]", selectType = XxlCrawlerConf.SelectType.VAL)
        private List<String> id_unitList;

        @PageFieldSelect(cssQuery = "[name=\"amount_cart_unit\"]", selectType = XxlCrawlerConf.SelectType.VAL)
        private List<String> amount_cart_unitList;

        @PageFieldSelect(cssQuery = "[name=\"amount_cart_unit\"]", selectType = XxlCrawlerConf.SelectType.VAL)
        private List<String> id_warrantyList;

        @PageFieldSelect(cssQuery = "[name=\"amount_cart_unit\"]", selectType = XxlCrawlerConf.SelectType.VAL)
        private List<String> id_bundleList;

        @PageFieldSelect(cssQuery = "[name=\"amount_cart_unit\"]", selectType = XxlCrawlerConf.SelectType.VAL)
        private List<String> promotionsList;


        //删除参数
        @PageFieldSelect(cssQuery = "a.unit-del", selectType = XxlCrawlerConf.SelectType.ATTR, selectVal = "hitscfs")
        private List<String> delHitsCfsList;

        @PageFieldSelect(cssQuery = "a.unit-del", selectType = XxlCrawlerConf.SelectType.ATTR, selectVal = "hitscfsmeta")
        private List<String> delHitsCfsMetaList;
        @PageFieldSelect(cssQuery = "a.unit-del", selectType = XxlCrawlerConf.SelectType.ATTR, selectVal = "data-unit-id")
        private List<String> delId_unitList;

        @PageFieldSelect(cssQuery = "[name=\"amount_cart_unit\"]", selectType = XxlCrawlerConf.SelectType.VAL)
        private List<String> delCountList;

    }


    private final String CARTID = "15331898985b629f0ae4634";
    private final String PHPSESSID = "lj48b3aj8asao3grgmtdfg37vh5jdsu7";

    public void CrawlItemDetailStop(String name) {
        END_STATE = false;
        System.out.println("停止！！" + name);
    }

    public void CrawlItemDetail(String name) {
        do {

            int max;
            max = iItemDetailService.findMaxItemDetailInventory() + 1;

            //查询需要爬取得商品
            final List<ItemDetail> itemDetailList = new ArrayList();

            JobLog jobLog = new JobLog();

            //头信息
            Map<String, String> headMap = getHeadMap();

            //头信息
            Map<String, String> cookieMap = getCookieMap();

            Item item = new Item();
            List<Item> itemList = itemService.selectItemList(item);

            IJobLogService jobLogService = (IJobLogService) SpringUtils.getBean(IJobLogService.class);

            //开始时间
            long startTime = System.currentTimeMillis();

            //日志信息
            jobLog.setJobName(name + "任务，第" + max + "次");
            jobLog.setJobGroup(name);
            jobLog.setMethodName(name);
            jobLog.setMethodParams(name);

            //转换list
            final String[] link = new String[itemList.size()];

            int j = 0;
            for (Item item1 : itemList) {
                link[j] = item1.getItemHref();
                j++;

            }

            //测试
            //link[0] = "https://saudi.souq.com/sa-en/diesel-mega-chief-men-s-black-dial-leather-band-watch-dz4344-8283904/i/";

            try {

            XxlCrawler crawler0 = new XxlCrawler.Builder()
                    .setUrls(link)
                    .setIfPost(true)
                    .setThreadCount(3)
                    .setPauseMillis(1000)
                    .setAllowSpread(false)
                    .setHeaderMap(headMap)
                    .setFailRetryCount(3)
                    //.setProxyMaker(proxyMaker)
                    .setCookieMap(cookieMap)
                    .setPageParser(
                            new PageParser<InventoryPageVo>() {
                                @Override
                                public boolean parse(Document html, Element pageVoElement, InventoryPageVo pageVo) {

                                    //如果第一个页面没有库存信息 说明商品的库存大于 10  需要使用模拟购物车的方式取出库存
                                    if (pageVo.getItem_Detail_Inventory() == null) {
                                        //添加到购物车
                                        addItemsAsCart(pageVo);
                                    } else {
                                        ItemDetail cartdetail = new ItemDetail();
                                        //商品名称
                                        cartdetail.setItemDetailName(pageVo.getItem_Detail_Name());
                                        //商品库存
                                        cartdetail.setItemDetailInventory(pageVo.getItem_Detail_Inventory());
                                        //设置商品链接
                                        cartdetail.setItemDetailHref(html.baseUri());

                                        itemDetailList.add(cartdetail);

                                    }
                                    return true;
                                }

                            }
                    )
                    .build();
            crawler0.start(true);



            //保存商品的详细信息
            iItemDetailService.insertItemDetailAsCrawlItemDetail(itemDetailList, max);

            //爬取购物车中的最大库存数量
            getItemsAsCart(max);

                //hibernateUtil.saveCategory((InventoryPageVo)crawler.getPageVo());
                //selectCartDetail();


                jobLog.setCreateTime(new Date());
                long times = System.currentTimeMillis() - startTime;
                // 任务状态 0：成功 1：失败
                jobLog.setStatus(Constants.SUCCESS);
                jobLog.setJobMessage(" 总共耗时：" + times + "毫秒");
            } catch (Exception e) {

                jobLog.setCreateTime(new Date());
                long times = System.currentTimeMillis() - startTime;
                // 任务状态 0：成功 1：失败
                jobLog.setStatus(Constants.FAIL);
                jobLog.setJobMessage(" 总共耗时：" + times + "毫秒");

            }finally{
                jobLogService.addJobLog(jobLog);
            }
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
        while (END_STATE);
    }


    /**
     * @Author lcx
     * @Date 2018/8/8 20:58
     * 把商品添加到购物车
     */
    private void addItemsAsCart(InventoryPageVo pageVo) {

        Map<String, String> headMap = getHeadMap();
        Map<String, String> cookieMap = getCookieMap();
        Map<String, String> paramMap = new HashMap<>();


        paramMap.put("hitsCfs", pageVo.getAdd_HitsCfs());
        paramMap.put("hitsCfsMeta", pageVo.getAdd_HitsCfsMeta());
        paramMap.put("action", "add_item_to_cart");
        paramMap.put("id_unit", pageVo.getAdd_Id_unit());
        paramMap.put("redirect_to", pageVo.getAdd_Redirect_to());
        paramMap.put("id_bundle", "0");
        paramMap.put("id_warranty", "1");

        final String[] link = {
                "https://uae.souq.com/ae-en/shopping_cart.php"
        };

        XxlCrawler crawler1 = new XxlCrawler.Builder()
                .setUrls(link)
                .setThreadCount(1).setPauseMillis(1000)
                .setAllowSpread(false)
                .setIfPost(true)
                .setHeaderMap(headMap)
                .setParamMap(paramMap)
                .setCookieMap(cookieMap)
                .setPageParser(
                        new PageParser<InventoryPageVo>() {
                            @Override
                            public boolean parse(Document html, Element pageVoElement, InventoryPageVo pageVo) {
                                return true;
                            }

                        }
                )
                .build();

        crawler1.start(true);

    }


    /**
     * @Author lcx
     * @Date 2018/8/8 21:09
     * 获取购物车
     */
    private void getItemsAsCart(int itemDetailCount) {

        Map<String, String> headMap = getHeadMap();

        Map<String, String> cookieMap = getCookieMap();

        final String[] link = {
                "https://uae.souq.com/ae-en/shopping_cart.php?aoc=f"
        };

        XxlCrawler crawler1 = new XxlCrawler.Builder()
                .setUrls(link)
                .setThreadCount(1).setPauseMillis(1000)
                .setAllowSpread(false)
                .setHeaderMap(headMap)
                .setFailRetryCount(3)
                .setCookieMap(cookieMap)
                .setPageParser(
                        new PageParser<InventoryPageVo>() {
                            @Override
                            public boolean parse(Document html, Element pageVoElement, InventoryPageVo pageVo) {
                                //拉取最大库存
                                getMaxItemDetailInventoryAsCart(pageVo, itemDetailCount);
                                return true;
                            }

                        }
                )
                .build();
        crawler1.start(true);
    }

    /**
     * @Author lcx
     * @Date 2018/8/8 21:12
     * 拉取购物车中商品的最大库存数量
     */
    private void getMaxItemDetailInventoryAsCart(InventoryPageVo pageVo, int itemDetailCount) {
        final List<ItemDetail> itemDetailList = new ArrayList<>();

        //获取购物车中的所有商品数量 开始遍历拉取最大数量
        for (int j = 0; j < pageVo.getDelHitsCfsList().size(); j++) {

            Map<String, String> cookieMap = getCookieMap();
            Map<String, String> headMap = new HashMap<>();
            Map<String, String> paramMap = new HashMap<>();

            paramMap.put("hitsCfs", pageVo.getDelHitsCfsList().get(j));
            paramMap.put("hitsCfsMeta", pageVo.getDelHitsCfsMetaList().get(j));
            paramMap.put("action", "update_item_quantity");
            paramMap.put("id_unit", pageVo.getDelId_unitList().get(j));
            //paramMap.put("id_warranty", id_warranty);
            paramMap.put("id_bundle", "0");
            paramMap.put("id_warranty", "1");
            paramMap.put("quantity", "99");
            paramMap.put("amount_cart_unit", "2");
            paramMap.put("promotions", "0");

            final String[] link = {
                    "https://uae.souq.com/ae-en/shopping_cart.php"
            };

            XxlCrawler crawler2 = new XxlCrawler.Builder()
                    .setUrls(link)
                    .setThreadCount(1).setPauseMillis(1000)
                    .setAllowSpread(false)
                    .setIfPost(true)
                    .setFailRetryCount(3)
                    .setParamMap(paramMap)
                    .setHeaderMap(headMap)
                    .setCookieMap(cookieMap)
                    .setPageParser(
                            new PageParser<InventoryPageVo>() {
                                @Override
                                public boolean parse(Document html, Element pageVoElement, InventoryPageVo pageVo) {
                                    return true;
                                }

                            }
                    )
                    .build();
            crawler2.start(true);

            //获取获得到的最大库存数量
            InventoryPageVo pageVoTem = (InventoryPageVo) crawler2.getPageVo();
            ItemDetail itemDetail = new ItemDetail();
            //名称
            itemDetail.setItemDetailName(pageVoTem.getItem_Detail_Name2().get(0));
            //库存
            itemDetail.setItemDetailInventory(pageVoTem.getItem_Detail_Inventory2().get(0));
            //链接
            itemDetail.setItemDetailHref(pageVoTem.getItem_Detail_Href2().get(0));
            //店铺名称
            itemDetail.setItemDetailStoreName(pageVoTem.getItem_Detail_Store_Name2().get(0));
            //如果商品不满10个则之前已经处理了 这里需要跳过
            if (!"null".equals(pageVoTem.getTxt_Alert().get(0))) {
                continue;
            }
            itemDetailList.add(itemDetail);
        }
        iItemDetailService.insertItemDetailAsCrawlItemDetail(itemDetailList, itemDetailCount);
    }


    /**
     * @Author lcx
     * @Date 2018/8/8 20:32
     * 获得head Map
     */
    private Map<String, String> getHeadMap() {

        Map<String, String> headMap = new HashMap<>();

        headMap.put("pragma", "no-cache");
        headMap.put("server", "Apache");
        headMap.put("strict-transport-security", "max-age=0");
        headMap.put("transfer-encoding", "chunked");
        headMap.put("vary", "Accept-Encoding");
        headMap.put("x-content-type-options", "nosniff");
        headMap.put("x-frame-options", "SAMEORIGIN");
        headMap.put("login_failed", "deleted");
        headMap.put("login_source", "deleted");

        return headMap;
    }

    /**
     * @Author lcx
     * @Date 2018/8/8 20:32
     * 获得cookie Map
     */
    private Map<String, String> getCookieMap() {

        Map<String, String> cookieMap = new HashMap<>();

        cookieMap.put("CARTID", CARTID);
        cookieMap.put(BUYER_CITY_SELECTED_DB.getDesc(), BUYER_CITY_SELECTED_DB.getCode());
        cookieMap.put("PHPSESSID", PHPSESSID);

        return cookieMap;
    }
}
